<?php

/**
 * @file
 * Integration with the Feeds module.
 */

/**
 * Implements hook_feeds_processor_targets_alter().
 */
function commerce_file_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_name) {
  $license_info = _commerce_file_collate_license_info();

  foreach (field_info_instances($entity_type, $bundle_name) as $name => $instance) {
    $info = field_info_field($name);
    if ($info['type'] != 'commerce_file') {
      continue;
    }

    // file import
    $targets[$name . ':file'] = array(
      'name' => check_plain($instance['label'] . ': File'),
      'callback' => 'commerce_file_set_file_target',
      'real_target' => $info['field_name'],
      'description' => t('The @label field file target.', array('@label' => $instance['label'])),
    );

    // license data info
    foreach ($license_info as $data_field => $data_info) {
      $name_label = $instance['label'] . ': Data: ' . drupal_ucfirst(str_replace('_', ' ', $data_field));
      $targets[$name . ':data:' . $data_field] = array(
        'name' => check_plain($name_label),
        'callback' => 'commerce_file_set_data_target',
        'real_target' => $info['field_name'],
        'description' => $data_info['property info']['description'],
      );
    }
  }
}


/**
 * File target callback for hook_feeds_processor_targets_alter().
 *
 * @param $source
 *   Field mapper source settings.
 * @param $entity
 *   An entity object, for instance a node object.
 * @param $target
 *   A string identifying the target on the entity.
 * @param $value
 *   The value to populate the target with.
 *
 * @see file_feeds_set_target()
 */
function commerce_file_set_file_target($source, $entity, $target, $value) {
  // extract field_name, sub_field should be 'file'
  list($target, $sub_field) = explode(':', $target, 2);

  if (empty($value)) {
    return;
  }
  module_load_include('inc', 'file', 'file.field');
  module_load_include('inc', 'commerce_file', 'includes/commerce_file.field');

  // Make sure $value is an array of objects of type FeedsEnclosure.
  if (!is_array($value)) {
    $value = array($value);
  }
  foreach ($value as $k => $v) {
    if (!($v instanceof FeedsEnclosure)) {
      if (is_string($v)) {
        $value[$k] = new FeedsEnclosure($v, 'application/octet-stream');
      }
      else {
        unset($value[$k]);
      }
    }
  }
  if (empty($value)) {
    return;
  }

  // Determine file destination.
  // @todo This needs review and debugging.
  list($entity_id, $vid, $bundle_name) = entity_extract_ids($entity->feeds_item->entity_type, $entity);
  $instance_info = field_info_instance($entity->feeds_item->entity_type, $target, $bundle_name);
  $info = field_info_field($target);
  $singular = $info['cardinality'] == 1;

  // set default file owner to root user for security
  $file_owner_uid = 1;

  // set destination and owner uid to entity uid if not anonymous
  $token_data = array();
  if (!empty($entity->uid)) {
    $file_owner_uid = $entity->uid;
    $token_data[$entity->feeds_item->entity_type] = $entity;
  }
  $destination = file_field_widget_uri($info, $instance_info, $token_data);

  // set default license data
  $data_default = array();

  // add license limits as inherited
  $license_info = _commerce_file_collate_license_info();
  if (!empty($license_info)) {
    $data_default = array_fill_keys(array_keys($license_info), COMMERCE_FILE_FIELD_INHERIT);
  }

  // merge any other instance data
  if (!empty($instance_info['settings']['data'])) {
    $data_default += $instance_info['settings']['data'];
  }

  // Populate entity.
  $i = 0;
  $field = isset($entity->$target) ? $entity->$target : array();
  $lang = LANGUAGE_NONE;
  foreach ($value as $v) {
    $file = $v->getFile($destination);
    if (empty($file) || empty($file->fid)) {
      continue;
    }

    // set file data and resave
    $save_file = FALSE;

    // set file owner
    if ($file->uid != $file_owner_uid) {
      $file->uid = $file_owner_uid;
      $save_file = TRUE;
    }

    // set proper mimetype
    $mimetype = file_get_mimetype($file->uri);
    if ($file->filemime != $mimetype) {
      $file->filemime = $mimetype;
      $save_file = TRUE;
    }

    // re-save file if anything changed
    if ($save_file) {
      file_save($file);
    }

    // ensure field array
    if (empty($field[$lang][$i])) {
      $field[$lang][$i] = array();
    }
    elseif(!is_array($field[$lang][$i])) {
      $field[$lang][$i] = array($field[$lang][$i]);
    }

    // merge file
    $field[$lang][$i] += (array)$file;

    // merge access limit defaults
    $field[$lang][$i] += array('data' => $data_default);

    // stop if only 1 item
    if ($singular) {
      break;
    }
    $i++;

  }
  $entity->{$target} = $field;
}

/**
 * Schema field target callback for hook_feeds_processor_targets_alter().
 *
 * @param $source
 *   Field mapper source settings.
 * @param $entity
 *   An entity object, for instance a node object.
 * @param $target
 *   A string identifying the target on the entity.
 * @param $value
 *   The value to populate the target with.
 */
function commerce_file_set_schema_target($source, $entity, $target, $value) {
  list($field_name, $sub_field) = explode(':', $target, 2);

  // Handle non-multiple value fields.
  if (!is_array($value)) {
    $value = array($value);
  }

  $field = isset($entity->$field_name) ? $entity->$field_name : array();
  $field_info = field_info_field($field_name);
  $singular = $field_info['cardinality'] == 1;

  $lang = LANGUAGE_NONE;
  foreach ($value as $i => $v) {
    $field[$lang][$i][$sub_field] = $v;

    if ($singular) {
      break;
    }
  }

  $entity->$field_name = $field;
}

/**
 * License data target callback for hook_feeds_processor_targets_alter().
 *
 * @param $source
 *   Field mapper source settings.
 * @param $entity
 *   An entity object, for instance a node object.
 * @param $target
 *   A string identifying the target on the entity.
 * @param $value
 *   The value to populate the target with.
 */
function commerce_file_set_data_target($source, $entity, $target, $value) {
  list($field_name, $field_data_name, $property_name) = explode(':', $target, 3);

  // Handle non-multiple value fields.
  if (!is_array($value)) {
    $value = array($value);
  }

  $field = isset($entity->$field_name) ? $entity->$field_name : array();
  $field_info = field_info_field($field_name);
  $singular = $field_info['cardinality'] == 1;

  $lang = LANGUAGE_NONE;
  foreach ($value as $i => $v) {
    $field[$lang][$i][$field_data_name][$property_name] = $v;

    if ($singular) {
      break;
    }
  }

  $entity->$field_name = $field;
}
